package com.cloud.basic.reference;

import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.text.DecimalFormat;

/**
 * @program: basic
 * @description: 软引用，弱引用
 * @author: Cloud
 * @create: 2020/11/26 14:28:32
 */
public class reference {

    static class testUser{
         private String name;
         private int age;

         public String getName() {
             return name;
         }

         public void setName(String name) {
             this.name = name;
         }

         public int getAge() {
             return age;
         }

         public void setAge(int age) {
             this.age = age;
         }

         public testUser(String name, int age){
             this.name = name;
             this.age = age;
         }

         @Override
         public String toString() {
             return "testUser{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     '}';
         }
     }

    public static void main(String[] args) throws InterruptedException {
//        testUser u = new testUser("张三",4);
//        SoftReference<testUser> softReference = new SoftReference<testUser>(u);
//        // 去除强引用
//        u = null;
//
//        System.out.println("内存不紧张"+softReference.get());
//        System.gc();
//        System.out.println(softReference.get());
//
//        System.out.println("内存紧张，只有7M的内存");
//        //分配7M左右，使内存空间紧张
//        Byte[] bytes = new Byte[1024 * 925 * 7];
//        System.gc();
//        System.out.println(softReference.get());// 此时内存因为内存紧张，软引用的内存已经被GC掉了。

        testUser u = new testUser("张三",4);
        WeakReference<testUser> weakReference = new WeakReference<testUser>(u);
        // 去除强引用
        u = null;

        System.out.println("内存不紧张："+weakReference.get());
        System.gc();
        System.out.println(weakReference.get());

        jvmInfo();
        //分配5M左右，使内存空间紧张
        Byte[] bytes = new Byte[1024 * 1024 * 3];
//        System.out.println();
//        System.out.println("内存紧张，只分配5M的内存出来");
        jvmInfo();
        System.gc();
        // 此时内存因为内存紧张，软引用的内存已经被GC掉了。
        System.out.println(weakReference.get());

//        System.out.println("java虚拟机从操纵系统那里挖到的最大的内存   maxMemory : "+Runtime.getRuntime().maxMemory()/1024/1024+"M");
//        System.out.println("java虚拟机已经从操作系统那里挖过来的内存   totalMemory : "+Runtime.getRuntime().totalMemory()/1024/1024+"M");
//        System.out.println("java虚拟机从操纵系统挖过来还没用上的内存   freeMemory : "+Runtime.getRuntime().freeMemory()/1024/1024+"M");
//        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//        byte[] b1 = new byte[3*1024*1024];
//        System.out.println("java虚拟机从操纵系统那里挖到的最大的内存   maxMemory "+Runtime.getRuntime().maxMemory()/1024/1024+"M");
//        System.out.println("java虚拟机已经从操作系统那里挖过来的内存   totalMemory : "+Runtime.getRuntime().totalMemory()/1024/1024+"M");
//        System.out.println("java虚拟机从操纵系统挖过来还没用上的内存   freeMemory : "+Runtime.getRuntime().freeMemory()/1024/1024+"M");
//        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
//        byte[] b2 = new byte[10*1024*1024];
//        System.out.println("java虚拟机从操纵系统那里挖到的最大的内存   maxMemory "+Runtime.getRuntime().maxMemory()/1024/1024+"M");
//        System.out.println("java虚拟机已经从操作系统那里挖过来的内存   totalMemory : "+Runtime.getRuntime().totalMemory()/1024/1024+"M");
//        System.out.println("java虚拟机从操纵系统挖过来还没用上的内存   freeMemory : "+Runtime.getRuntime().freeMemory()/1024/1024+"M");
//        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

        /**
         * used：加载的类的空间量。
         * capacity： 当前分配块的元数据的空间。
         * committed： 空间块的数量。
         * reserved：元数据的空间保留(总空间)。
         * */

//        byte[] bytes01 = new byte[1 * 1024 * 1024];
//        System.out.println("分配了1M内存");
//        jvmInfo();
//        Thread.sleep(3000);
//        byte[] bytes02 = new byte[4 * 1024 * 1024];
//        System.out.println("分配了4M内存");
//        jvmInfo();
    }


    static private String toM(long maxMemory) {
        float num = (float) maxMemory / (1024 * 1024);
        DecimalFormat df = new DecimalFormat("0.00");// 格式化小数
        String s = df.format(num);// 返回的是String类型
        return s;
    }

    public static void jvmInfo(){
        // java虚拟机从操纵系统那里挖到的最大的内存
        long maxMemory = Runtime.getRuntime().maxMemory();
        System.out.println("java虚拟机从操纵系统那里挖到的最大的内存  maxMemory = " + maxMemory + "," + toM(maxMemory) + "M");

        // java虚拟机已经从操作系统那里挖过来的内存
        long totalMemory = Runtime.getRuntime().totalMemory();
        System.out.println("java虚拟机已经从操作系统那里挖过来的内存  totalMemory:" + totalMemory + "," + toM(totalMemory) + "M");

        // java虚拟机从操纵系统挖过来还没用上的内存
        long freeMemory = Runtime.getRuntime().freeMemory();
        System.out.println("java虚拟机从操纵系统挖过来还没用上的内存  freeMemory:" + freeMemory + "," + toM(freeMemory) + "M");
    }
}
